#ifndef _SRC_NET_INET_ADDRESS_H_
#define _SRC_NET_INET_ADDRESS_H_

#include <bits/sockaddr.h>

#include <string>
#include <string_view>

#include "src/net/sockets_opt.h"
#include "src/base/utils.h"

namespace fio66::net{
///
/// Wrapper of sockaddr_in.
///
/// This is an POD interface class.
class InetAddress {
 public:
  /// Constructs an endpoint with given port number.
  /// Mostly used in TcpServer listening.
  explicit InetAddress(uint16_t port = 0, bool loopbackOnly = false,
                       bool ipv6 = false);

  /// Constructs an endpoint with given ip and port.
  /// @c ip should be "1.2.3.4"
  InetAddress(std::string_view ip, uint16_t port, bool ipv6 = false);

  /// Constructs an endpoint with given struct @c sockaddr_in
  /// Mostly used when accepting new connections
  explicit InetAddress(const struct sockaddr_in& addr) : addr_(addr) {}

  explicit InetAddress(const struct sockaddr_in6& addr) : addr6_(addr) {}

  // 如代码
  sa_family_t Family() const { return addr_.sin_family; }
  // 将ip转为字符串的形式x.x.x.x
  std::string ToIp() const;
  // 将ip和端口转为x.x.x.x:port的形式
  std::string ToIpPort() const;
  // 获取端口号
  uint16_t Port() const;

  // default copy/assignment are Okay
  // 如代码,将sockaddr_in6格式转为sockaddr
  const struct sockaddr* GetSockAddr() const {
    return sockets::sockaddr_cast(&addr6_);
  }
  void SetSockAddrInet6(const struct sockaddr_in6& addr6) { addr6_ = addr6; }

  // 获取IP的网络字节序的值
  uint32_t IPV4NetEndian() const;
  // 获取端口的网络字节序的值
  uint16_t PortNetEndian() const { return addr_.sin_port; }

  // resolve hostname to IP address, not changing port or sin_family
  // return true on success.
  // thread safe
  static bool Resolve(std::string_view hostname, InetAddress* result);
  // static std::vector<InetAddress> resolveAll(const char* hostname, uint16_t
  // port = 0);

  // set IPv6 ScopeID
  void SetScopeId(uint32_t scope_id);

 private:
  union {
    struct sockaddr_in addr_;
    struct sockaddr_in6 addr6_;
  };
};
}  // namespace fio66::net

#endif  // _SRC_NET_INET_ADDRESS_H_
